﻿using MCUPackage;
using MCUPackage.DesignEditor;
using MCUPackage.Utils;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;

namespace SxPackages.STC32G.Models
{
	/// <summary>
	/// 内置时钟选项
	/// </summary>
	[Serializable]
	class RTCOptions
	{
		protected STC32GQFP64 mParent = null;

		[Category("时钟配置"),
		DisplayName("功能启用"),
		Description("是否启用内置实时时钟功能"),
		JsonProperty(Order = 100),
		DefaultValue(false)]
		public bool Enable { get; set; } = false;

		[Category("时钟配置"),
		DisplayName("是否使用外部时钟源"),
		Description("true使用外部32.768KHz时钟源, false使用内部32KHz时钟源"),
		DefaultValue(false)]
		public bool Clock { get; set; } = false;

		private DateTime mInitValue = DateTime.Now;
		[Category("时钟配置"),
		DisplayName("时钟初始值"),
		Description("时钟初始值"),
		TypeConverter(typeof(RTCFormatConvertor))]
		public DateTime InitValue
		{
			get => mInitValue;
			set
			{
				if (value != mInitValue)
				{
					if (value.Year < 2000 || value.Year > 2099)
					{
						GuiUtils.MsgBox("请输入有效值!");
						return;
					}

					mInitValue = value;
				}
			}
		}

		[Category("时钟配置"),
		DisplayName("使能闹钟"),
		Description("是否启用闹钟中断, 每天中断一次"),
		DefaultValue(false)]
		public bool EnableAlarm { get; set; } = false;

		[Category("时钟配置"),
		DisplayName("闹钟设置"),
		Description("闹钟中断时间, 每天的时:分:秒"),
		TypeConverter(typeof(TimeFormatConvertor))]
		public DateTime Alarm { get; set; } = DateTime.Now;

		[Category("时钟配置"),
		DisplayName("使能日中断"),
		Description("是否启用每天0点0分0秒的中断"),
		DefaultValue(false)]
		public bool EnableDay { get; set; } = false;

		[Category("时钟配置"),
		DisplayName("使能小时中断"),
		Description("是否启用每小时0分0秒的中断"),
		DefaultValue(false)]
		public bool EnableHour { get; set; } = false;

		[Category("时钟配置"),
		DisplayName("使能分钟中断"),
		Description("是否启用每分钟0秒的中断"),
		DefaultValue(false)]
		public bool EnableMinute { get; set; } = false;

		[Category("时钟配置"),
		DisplayName("使能秒中断"),
		Description("是否启用每秒的中断"),
		DefaultValue(false)]
		public bool EnableSecond { get; set; } = false;

		[Category("时钟配置"),
		DisplayName("使能1/2秒中断"),
		Description("是否启用每1/2秒的中断"),
		DefaultValue(false)]
		public bool EnableSecondPer2 { get; set; } = false;

		[Category("时钟配置"),
		DisplayName("使能1/8秒中断"),
		Description("是否启用每1/8秒的中断"),
		DefaultValue(false)]
		public bool EnableSecondPer8 { get; set; } = false;

		[Category("时钟配置"),
		DisplayName("使能1/32秒中断"),
		Description("是否启用每1/32秒的中断"),
		DefaultValue(false)]
		public bool EnableSecondPer32 { get; set; } = false;

		[Category("时钟配置"),
		DisplayName("中断优先级"),
		Description("中断优先级等级设置"),
		DefaultValue(PriorityTypes.最低级)]
		public PriorityTypes Priority { get; set; } = PriorityTypes.最低级;

		/// <summary>
		/// 是否开启中断
		/// </summary>
		/// <returns></returns>
		public bool HasInterrupt()
		{
			if (EnableAlarm || EnableDay || EnableHour || EnableMinute || EnableSecond
				|| EnableSecondPer2 || EnableSecondPer8 || EnableSecondPer32)
			{
				return true;
			}

			return false;
		}

		/// <summary>
		/// 初始化模板
		/// </summary>
		private const string TEMPLATE =
@"	attr.RTC_Clock  = {0};	//RTC 时钟, RTC_IRC32KCR, RTC_X32KCR
	attr.RTC_Enable = ENABLE;			//RTC功能使能,   ENABLE, DISABLE
	attr.RTC_Year   = {1};					//RTC 年, 00~99, 对应2000~2099年
	attr.RTC_Month  = {2};					//RTC 月, 01~12
	attr.RTC_Day    = {3};					//RTC 日, 01~31
	attr.RTC_Hour   = {4};					//RTC 时, 00~23
	attr.RTC_Min    = {5};					//RTC 分, 00~59
	attr.RTC_Sec    = {6};					//RTC 秒, 00~59
	attr.RTC_Ssec   = 0;					//RTC 1/128秒, 00~127

	attr.RTC_ALAHour= {7};					//RTC 闹钟时, 00~23
	attr.RTC_ALAMin = {8};					//RTC 闹钟分, 00~59
	attr.RTC_ALASec = {9};					//RTC 闹钟秒, 00~59
	attr.RTC_ALASsec= 0;					//RTC 闹钟1/128秒, 00~127
	RTC_Inilize(&attr);
	NVIC_RTC_Init({10}, {11});		//中断使能, RTC_ALARM_INT/RTC_DAY_INT/RTC_HOUR_INT/RTC_MIN_INT/RTC_SEC_INT/RTC_SEC2_INT/RTC_SEC8_INT/RTC_SEC32_INT/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3";

		/// <summary>
		/// 返回NVIC配置
		/// </summary>
		/// <returns></returns>
		private string GetNVIC()
		{
			List<string> lst = new List<string>();
			if (this.EnableAlarm)
			{
				lst.Add("RTC_ALARM_INT");
			}
			if (this.EnableDay)
			{
				lst.Add("RTC_DAY_INT");
			}
			if (this.EnableHour)
			{
				lst.Add("RTC_HOUR_INT");
			}
			if (this.EnableMinute)
			{
				lst.Add("RTC_MIN_INT");
			}
			if (this.EnableSecond)
			{
				lst.Add("RTC_SEC_INT");
			}
			if (this.EnableSecondPer2)
			{
				lst.Add("RTC_SEC2_INT");
			}
			if (this.EnableSecondPer8)
			{
				lst.Add("RTC_SEC8_INT");
			}
			if (this.EnableSecondPer32)
			{
				lst.Add("RTC_SEC32_INT");
			}

			if (lst.Count < 1)
			{
				return false.ToEnable();
			}

			return string.Join(" | ", lst.ToArray());
		}

		public bool AppendConfig(List<string[]> aLst)
		{
			if (!this.Enable)
			{
				return false;
			}

			string name = "RTC_Config";
			StringBuilder funcSb = new StringBuilder();
			funcSb.Append(TemplateHelper.GetFunctionCommit("片内实时时钟模块初始化"));
			funcSb.AppendLine($"PRIVATE void {name}(void)").AppendLine("{");
			funcSb.AppendLine("\tRTC_InitTypeDef attr;");

			funcSb.AppendLine();

			funcSb.AppendFormat(TEMPLATE, this.Clock ? "RTC_X32KCR" : "RTC_IRC32KCR",
							this.InitValue.Year % 100, this.InitValue.Month, this.InitValue.Day,
							this.InitValue.Hour, this.InitValue.Minute, this.InitValue.Second,
							this.Alarm.Hour, this.Alarm.Minute, this.Alarm.Second,
							this.GetNVIC(), this.Priority.ToDescription()).AppendLine();

			funcSb.AppendLine("}");
			aLst.Add(new string[] { funcSb.ToString(), $"{name}();" });

			return true;
		}

		public RTCOptions(STC32GQFP64 aParent)
		{
			this.mParent = aParent;
		}
	}
}
